use crate::{coordinate::Coord, layout::Layout, state::State};
use derive_more::Deref;
use std::{
    ops::{Index, IndexMut},
    rc::Rc,
};

#[derive(Clone, Debug, PartialEq, Eq, Deref)]
pub struct ClickSet {
    #[deref]
    layout: Rc<Layout>,
    clicks: Box<[usize]>,
}

impl Index<Coord> for ClickSet {
    type Output = usize;
    fn index(&self, index: Coord) -> &Self::Output {
        &self.clicks[self.get_index(index).expect("该坐标没有格子")]
    }
}
impl IndexMut<Coord> for ClickSet {
    fn index_mut(&mut self, index: Coord) -> &mut Self::Output {
        let index = self.get_index(index).expect("该坐标没有格子");
        &mut self.clicks[index]
    }
}

impl ClickSet {
    pub fn new(layout: Rc<Layout>) -> Self {
        let clicks = vec![0; layout.cell_count()].into_boxed_slice();
        Self { layout, clicks }
    }

    pub fn iter_clicks(&self) -> impl Iterator<Item = Coord> + '_ {
        self.iter_cells()
            .zip(self.clicks.iter())
            .flat_map(|(coord, &n)| std::iter::repeat(coord).take(n))
    }

    pub fn run(&self, s: &mut State) -> usize {
        assert!(**self == **s); // 应为同一布局
        self.iter_clicks()
            .map(|coord| s.trigger_rotate(coord))
            .sum()
    }

    pub fn clicks(&self) -> &[usize] {
        &self.clicks
    }

    pub fn clicks_mut(&mut self) -> &mut [usize] {
        &mut self.clicks
    }
}
